<?php
/**
 *  Connection management class
 *
 */
class Yz_SQL_Adapter
    extends Yz_Class
{

    const CONFIG_OPTION_NAME = 'sql.connection';

    /** The currently open connections [name => connection]
     *  @var array[string=>Yz_SQL_Adapter_Interface]
     */
    protected $connections = array();

    /** singleton
     *  @var Yz_SQL_Adapter
     */
    protected static $instance;


    /************************************
     *         Public methods          *
     ************************************/


    /** selectConnection() : select (and open if not opened) a connection to a SQL server
     *  with the parameters given in system config (@const CONFIG_OPTION_NAME) under the name
     *  (or 'default')
     *  @param string $name
     *  @return Yz_SQL_Adapter_Interface
     *  @throw Yz_Exception_InvalidParameter if name is given and is not a valid name
     *  @throw Yz_SQL_Exception, and the adapter's exceptions on failing to connect
     */
    public static function selectConnection( $name=null )
    {
        if (null === $name) {
            $name = 'default';
        } else {
            $name = Yz_String::testNotEmpty($name);
        }
        $mgr = self::getInstance();
        return $mgr->useNamedConnection($name, null);
    }

    /** create a named connection to database specified by dsn
     *  @param string $name
     *  @param string $dsn
     *  @return Yz_SQL_Adapter_Interface
     *  @throw Yz_Exception_InvalidParameter if name is given and is not a valid name
     *  @throw Yz_SQL_Exception, and the adapter's exceptions on failing to connect
     */
    public static function createConnection( $name, $dsn )
    {
        $name = Yz_String::testNotEmpty($name);
        $dsn = Yz_String::testNotEmpty($dsn);
        $mgr = self::getInstance();
        return $mgr->useNamedConnection($name, $dsn);
    }


    /************************************
     *       protected methods          *
     ************************************/


    /**
     *  static getInstance(): singleton method
     *
     */
    protected static function getInstance()
    {
        debug();

        $i =& self::$instance;
        if ( null === $i ) {
            $i = new self;
        }
        return $i;
    } // getInstance()


    protected function __construct()
    {
        return;
    }

    /** manage the connections by name
     *
     *  find a connection by name or try to create it if it doesn't exist
     *      (using a dsn from the system config option @const CONFIG_OPTION_NAME )
     *      couldn't find a more suitable name
     *
     */
    protected function useNamedConnection( $name, $dsn )
    {
        $c =& $this->connections;
        if (! array_key_exists($name, $c)) {
            if (null === $dsn) {
                $dsn = Yz::getConfig()->fetchString( self::CONFIG_OPTION_NAME . '.' . $name );
                if (! $dsn) {
                    throw new Yz_SQL_Exception("Failed to open connection '$name'");
                }
            }
            $c[$name] = $this->connect($dsn);
        }
        return $c[$name];
    }



    /** create a connection specified by dsn
     *  @param string $dsn
     *  @return Yz_SQL_Adapter_Interface
     *  @throw Yz_SQL_Exception, and the adapter's exceptions on failing to connect
     *  @todo create different adapter types based on dsn schema (e.g. pgsql://)
     */
    protected function connect( $dsn=null )
    {
        $conn = new Yz_SQL_Adapter_Mysqli($dsn);
        return $conn;
    }

}
